package com.uxsino.simo.indicator.retractor;

import com.google.common.base.Strings;
import com.uxsino.commons.utils.config.ConfigProp;
import com.uxsino.simo.networkentity.EntityInfo;
import com.uxsino.simo.query.QueryContext;
import com.uxsino.simo.query.QueryTemplate;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public abstract class TextListRetractor extends ListValueRetractor {

    Logger logger = LoggerFactory.getLogger(TextListRetractor.class);

    @ConfigProp(name = "prefix_pattern", trim = false)
    public String prefixPattern;

    @ConfigProp(name = "surffix_pattern", trim = false)
    public String surffixPattern;

    @ConfigProp(name = "row_delimeter", trim = false)
    public String rowDelimeter;

    protected Map<String, Integer> columnNames;

    public TextListRetractor() {
        columnNames = new HashMap<>();
        rowDelimeter = "\n";
    }

    @Override
    public Object doRetract(EntityInfo entity, QueryContext ctxt, QueryTemplate qt, Object obj) {
        String buf = getTable((String) obj);

        String[] lines = getLines(buf);

        ArrayList<Map<String, Object>> records = new ArrayList<Map<String, Object>>();

        for (String line : lines) {

            String[] rec = splitRow(line);
            if (rec == null) {
                continue;
            }
            HashMap<String, Object> fieldValues = new HashMap<String, Object>();
            for (ColumnEntry entry : columnEntries) {
                Object value = null;

                // <cloumn col_id="1" field="fieldName">
                String s = getFieldString(entry.index, rec);
                if (!StringUtils.isEmpty(s)) {
                    value = entry.retractor.retract(entity, ctxt, qt, s);
                    fieldValues.put(entry.field.getName(), value);
                } else {
                    // System.out.println("here: " + entry.field.name);
                }

            }
            if (!fieldValues.isEmpty()) {
                records.add(fieldValues);
            }
        }
        return records;
    }

    protected String getTable(String buf) {

        if (prefixPattern != null) {
            Pattern pattern = Pattern.compile(prefixPattern, Pattern.DOTALL);
            Matcher m = pattern.matcher(buf);
            if (m != null) {
                buf = m.replaceFirst("");
            }
        }

        if (surffixPattern != null) {
            Pattern pattern = Pattern.compile(surffixPattern, Pattern.DOTALL);
            Matcher m = pattern.matcher(buf);
            if (m != null) {
                buf = m.replaceFirst("");
            }
        }
        return buf;
    }

    protected String[] getLines(String s) {
        return s.split(rowDelimeter);
    }

    protected String getFieldString(String index, String[] record) {
        if(Strings.isNullOrEmpty(index)){
            return null;
        }
        int i = columnNames.getOrDefault(index, -1);
        if (i == -1) {
            try {
                i = Integer.parseInt(index);
            } catch (NumberFormatException e) {
                logger.error("parse " + index, e);
            }
        }
        if (i < 1 || i > record.length) {
            return null;
        }

        return record[i - 1];
    }

    protected abstract String[] splitRow(String row);

}
